/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.Arrays;

class Obj {
    public double value = 0;
    Obj(double value) {
        this.value = value;
    }
}

class StaticFuncCallCfg {
    public static int global_value = 0;
    public static int[] arr = {12,43,56,76,89,54,45,32,35,47,46,44,21,37,84};
}


class Example {
    //static With parameters
    public static int Foo(int[] resources, int i, int i3, int resourcesLength){
        if ((resources[i % i3 & (resourcesLength - 1)] & 1) == 0) {
            i3 += 1;
        } else {
            i3 += 2;
        }
        return i3;
    }

    //static Without parameters
    public static Obj parameterlessFoo() {
        Obj[] res = {new Obj(0), new Obj(0), new Obj(0), new Obj(0), new Obj(0)};
        Obj[] resources = StaticFuncCall.GenerateFakeRandomObject();
        for (int i = 0; i < 200; i++) {
            res[i % 5] = resources[i % 15];
        }
        return res[1];
    }

    //static Different  parameters
    public static double DifferentFoo(int[] resources, int i, double i3, int resourcesLength) {
        if ((resources[(int)(i % i3) & (resourcesLength - 1)] & 1) == 0) {
            i3 += 1.1;
        } else {
            i3 += 2.1;
        }
        return i3;
    }

    //static Default  parameters
    public static int DefaultFoo(int[] resources, int i, int i3, int resourcesLength) {
        if ((resources[i % i3 & (resourcesLength - 1)] & 1) == 0) {
            i3 += 1;
        } else {
            i3 += 2;
        }
        return i3;
    }

    //static Variable  parameters
    public static void VariableFoo(int a, String b, boolean c) {
        StaticFuncCallCfg.arr[StaticFuncCallCfg.global_value] += 1;
    }

    //static ...Args  parameters
    public static void argsFoo(int[] ...args) {
        StaticFuncCallCfg.global_value += 1;
    }
}
class StaticFuncCall {

    public static int[] GenerateFakeRandomInteger() {
        int[] resource = new int[]{12, 43, 56, 76, 89, 54, 45, 32, 35, 47, 46, 44, 21, 37, 84};
        return resource;
    }


    public static Obj[] GenerateFakeRandomObject() {
        Obj[] resource = new Obj[15];
        Arrays.fill(resource, new Obj(0));
        for (int i = 0; i < 15; i++) {
            double random = Math.random() * (10) + 1;
            resource[i] = new Obj(random);
        }
        return resource;
    }

    public static double RunStaticFunction() {
        int count = 10000000;
        int i3 = 1;
        int[] resources = GenerateFakeRandomInteger();
        double  startTime = System.nanoTime();
        int resourcesLength = resources.length;
        for (int i = 0; i < count; i++) {
           i3 =  Example.Foo(resources, i, i3, resourcesLength);
        }
        double  midTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
        }
        double  endTime = System.nanoTime();
        double time = ((midTime - startTime) - (endTime - midTime)) / 1000000;
        System.out.println("res: " + i3);
        System.out.println("Static Function Call - RunStaticFunction:\t"+time+"\tms");
        return time;
    }
// let runner2 = new BenchmarkRunner("Static Function Call - RunNormalCall", RunStaticFunction);
// runner2.run();

    public static double RunParameterlessStaticFunction() {
        int count = 10000;
        StaticFuncCallCfg.global_value = 0;
        Obj i3 = new Obj(1);
        double  startTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
            i3 = Example.parameterlessFoo();
        }
        double  midTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
        }
        double  endTime = System.nanoTime();
        double time = ((midTime - startTime) - (endTime - midTime)) / 1000000;
        System.out.println("res: " + i3);
        System.out.println("Static Function Call - RunParameterlessStaticFunction:\t"+time+"\tms");
        return time;
    }

// let runner1 = new BenchmarkRunner("Static Function Call - RunParameterlessCall", RunParameterlessStaticFunction);
// runner1.run();

     public static double RunNormalDifStaticFunc() {
        int count = 10000000;
        StaticFuncCallCfg.global_value = 0;
        double i3 = 1.1;
        int[] resources = GenerateFakeRandomInteger();
        int resourcesLength = resources.length;
        double  startTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
            i3 = Example.DifferentFoo(resources, i, i3, resourcesLength);
        }
        double  midTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
        }
        double  endTime = System.nanoTime();
        double time = ((midTime - startTime) - (endTime - midTime)) / 1000000;
        System.out.println("res: " + i3);
         System.out.println("Static Function Call - RunNormalDifStaticFunc:\t"+time+"\tms");
        return time;
    }

// let runner3 = new BenchmarkRunner("Static Function Call - RunNormalDifferentCall", RunNormalDifStaticFunc);
// runner3.run();

    public static double RunNormalVariableFStaticFunc() {
        int count = 10000000;
        StaticFuncCallCfg.global_value = 0;
        double  startTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
            Example.VariableFoo(1, "2", true);
        }
        double  midTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
        }
        double  endTime = System.nanoTime();
        double time = ((midTime - startTime) - (endTime - midTime)) / 1000000;
        System.out.println("Static Function Call - RunNormalVariableFStaticFunc:\t"+time+"\tms");
        return time;
    }

    // let runner4 = new BenchmarkRunner("Static Function Call - RunNormalVariableFCall", RunNormalVariableFStaticFunc);
// runner4.run();
    public static double RunNormalDefStaticCall() {
        int count = 10000000;
        StaticFuncCallCfg.global_value = 0;
        int i3 = 1;
        int[] resources = GenerateFakeRandomInteger();
        int resourcesLength = resources.length;
        double  startTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
            i3 = Example.DefaultFoo(resources, i, i3, resourcesLength);
        }
        double  midTime = System.nanoTime();
        for (int i = 0; i < count; i++) {
        }
        double  endTime = System.nanoTime();
        double time = ((midTime - startTime) - (endTime - midTime)) / 1000000;
        System.out.println("res: " + i3);
        System.out.println("Static Function Call - RunNormalDefStaticCall:\t"+time+"\tms");
        return time;
    }
// let runner5 = new BenchmarkRunner("Static Function Call - RunNormalDefCall", RunNormalDefCall);
// runner5.run();

}

class Benchmark {
    public static void main(String[] args) {
        StaticFuncCall.RunStaticFunction();
        StaticFuncCall.RunParameterlessStaticFunction();
        StaticFuncCall.RunNormalDifStaticFunc();
        StaticFuncCall.RunNormalVariableFStaticFunc();
        StaticFuncCall.RunNormalDefStaticCall();
        // System.out.println("Ts Method Call Is End, global_value value: \t"+StaticFuncCallCfg.global_value);
    }
}